package com.tjhk.test.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tjhk.test.entity.CheckData;
import com.tjhk.test.entity.vo.CheckDataVo;
import com.tjhk.test.model.Result;
import com.tjhk.test.model.ResultGenerator;
import com.tjhk.test.service.CheckDataService;
import com.tjhk.test.util.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author ：little grape
 * @description：TODO
 * @date ：2022/12/10 16:54
 */

@Api(tags = "数据访问")
@RestController
@RequestMapping("api.data")
public class CheckDataController {

    @Resource
    private CheckDataService checkDataService;
    /**
     * （1）温江区：临江路、四川电力职业技术学院，区的计算权重分别为0.8、0.2；
     *          （2）郫都区：金泉两河、郫都党校，区的计算权重分别为0.3、0.7；
     *          （3）双流区：永安小学、白河闸门管理房，区的计算权重分别为0.4、0.6；
     *          （4）彭州市：彭州延秀小学
     *          （5）崇州市：紫园
     */
    private Map<String,String> siteMap = new HashMap<String,String>(){{
        put("临江路","临江区");
        put("四川电力职业技术学院","临江区");
        put("金泉两河","郫都区");
        put("郫都党校","郫都区");
        put("永安小学","双流区");
        put("白河闸门管理房","双流区");
        put("彭州延秀小学","彭州市");
        put("紫园","崇州市");
    }};
    private Map<String,List<String>> countyMap = new HashMap<String,List<String>>(){{
        put("临江区",Arrays.asList("临江路","四川电力职业技术学院"));
        put("郫都区",Arrays.asList("金泉两河","郫都党校"));
        put("双流区",Arrays.asList("永安小学","白河闸门管理房"));
        put("彭州市",Arrays.asList("彭州延秀小学"));
        put("崇州市",Arrays.asList("紫园"));
    }};
    private Map<String,Double> factorsMap = new HashMap<String,Double>(){{
        put("临江路",0.8);
        put("四川电力职业技术学院",0.2);
        put("金泉两河",0.3);
        put("郫都党校",0.7);
        put("永安小学",0.4);
        put("白河闸门管理房",0.6);
        put("彭州延秀小学",1.0);
        put("紫园",1.0);
    }};

    @ApiOperation(value = "上传样本数据",notes = "仅支持.xlsx",httpMethod = "POST")
    @ApiImplicitParam(name = "excelFile",value = "文件",required = true,dataType="MultipartFile",allowMultiple = true,paramType = "query")
    @PostMapping("/upload")
    public Result upload(@RequestParam("excelFile") MultipartFile excelFile) throws Exception {
        if (excelFile.isEmpty()) {
            return ResultGenerator.genFailResult("文件为空！");
        } else {
            try {
                InputStream is = excelFile.getInputStream();
                Map<String,String[][]> map = ExcelUtil.readExcel(is);
                // 测试可传多个sheet'
                AtomicInteger num = new AtomicInteger();
                map.forEach((k,v)->{
                    boolean flag = checkDataService.saveExcelValues(Arrays.copyOfRange(v,1,v.length));
                    if (flag){
                        num.addAndGet(v.length - 1);
                    }
                });
                // 正式环境
//                if (map.size() ==  1){
//                    String[][] excelValues = map.values().iterator().next();
//                    checkDataService.saveExcelValues(Arrays.copyOfRange(excelValues,1,excelValues.length));
//                    return ResultGenerator.genSuccessResult();
//                }else {
//                    return ResultGenerator.genFailResult("请只上传一个sheet！");
//                }
                return ResultGenerator.genSuccessResult("共上传"+num+"条数据！");
            }catch (Exception e){

            }
        }
        return ResultGenerator.genFailResult("文件错误！");
    }

    @ApiOperation("查")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "stTime", value = "开始时间", required = false),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = false)
    })
    @GetMapping("/query")
    public Result query(String stTime, String endTime) {
        List<CheckData> list = checkDataService.list(new LambdaQueryWrapper<CheckData>()
                .ge(CheckData::getCollectTime,stTime)
                .le(CheckData::getCollectTime,endTime)
                .orderByAsc(CheckData::getCollectTime)
        );
        if (list.size() == 0){
            return ResultGenerator.genFailResult("无该时间段数据，请上传！");
        }
        try {
            Map<String,List<CheckData>> map = list.stream().collect(Collectors.groupingBy(CheckData::getSiteName));
            // 当前时刻
            Map<String,List<CheckData>> mapc = list.stream().filter(s->s.getCollectTime().equals(list.get(list.size() - 1).getCollectTime()))
                    .collect(Collectors.groupingBy(CheckData::getSiteName));
            List<CheckDataVo> checkDataVos = new ArrayList<>();
            DecimalFormat df = new DecimalFormat("#.#");
            long disTime = LocalDateTime.parse(stTime,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                    .until(LocalDateTime.parse(endTime,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), ChronoUnit.HOURS) + 1;

            map.forEach((k,v)->{
                CheckDataVo checkDataVo = new CheckDataVo();
                checkDataVo.setSiteName(k);
                checkDataVo.setPm25(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getPm25())))));
                checkDataVo.setPm10(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getPm10())))));
                checkDataVo.setNo2(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getNo2())))));
                checkDataVo.setCo(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getCo())))));
                checkDataVo.setO3(df.format(v.stream().map(s->Double.valueOf(s.getO3())).collect(Collectors.toList()).stream().max(Comparator.naturalOrder()).orElse(0.0)));
                checkDataVo.setAqi(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getAqi())))));
                checkDataVo.setPp(v.stream().map(s->s.getPp()).filter(s->!s.equals("—")).distinct().collect(Collectors.joining(", ")));
                if (mapc.get(k)!=null){
                    // 此时的数据
                    CheckData c = mapc.get(k).get(0);
                    checkDataVo.setPpc(c.getPp());
                    checkDataVo.setAqic(c.getAqi());
                    if (mapc.get(k).get(0).getPp().equals("PM2.5")){
                        checkDataVo.setPpcv(c.getPm25());
                    }
                    if (mapc.get(k).get(0).getPp().equals("PM10")){
                        checkDataVo.setPpcv(c.getPm10());
                    }
                    if (mapc.get(k).get(0).getPp().equals("SO2")){
                        checkDataVo.setPpcv(c.getSo2());
                    }
                    if (mapc.get(k).get(0).getPp().equals("NO2")){
                        checkDataVo.setPpcv(c.getNo2());
                    }
                    if (mapc.get(k).get(0).getPp().equals("CO")){
                        checkDataVo.setPpcv(c.getCo());
                    }
                    if (mapc.get(k).get(0).getPp().equals("O3")){
                        checkDataVo.setPpcv(c.getO3());
                    }
                    if (mapc.get(k).get(0).getPp().equals("NO")){
                        checkDataVo.setPpcv(c.getNo());
                    }
                    if (mapc.get(k).get(0).getPp().equals("NOx")){
                        checkDataVo.setPpcv(c.getNox());
                    }
                }
                if(disTime < 24){
                    checkDataVo.setPm10r(df.format((75*24 - v.stream().mapToDouble(s->Double.valueOf(s.getPm10())).sum())/(24-disTime)));
                    checkDataVo.setPm25r(df.format((75*24 - v.stream().mapToDouble(s->Double.valueOf(s.getPm25())).sum())/(24-disTime)));
                }else {
                    checkDataVo.setPm10r("—");
                    checkDataVo.setPm25r("—");
                }
                checkDataVo.setCountyName(siteMap.get(k));
                checkDataVos.add(checkDataVo);
            });
            Map<String,List<CheckDataVo>> res = checkDataVos.stream().collect(Collectors.groupingBy(CheckDataVo::getCountyName));
            res.forEach((k,v)->{
                CheckDataVo vo = new CheckDataVo("0");
                if (!k.equals("崇州市")&&!k.equals("彭州市")){
                    if (v.size() == 2){
                        vo.setSiteName(k);
                        vo.setPp(v.get(0).getPp());
                        vo.setPpc(v.get(0).getPp());
                        vo.setAqic(v.get(0).getAqi());
                        vo.setPpcv(v.get(0).getPpcv());
                        v.forEach(s->{
                            Double f = factorsMap.get(s.getSiteName());
                            if (f != null){
                                vo.setPm25(df.format(Double.valueOf(vo.getPm25()) + Double.valueOf(s.getPm25())*f));
                                vo.setPm10(df.format(Double.valueOf(vo.getPm10()) + Double.valueOf(s.getPm10())*f));
                                vo.setNo2(df.format(Double.valueOf(vo.getNo2()) + Double.valueOf(s.getNo2())*f));
                                vo.setCo(df.format(Double.valueOf(vo.getCo()) + Double.valueOf(s.getCo())*f));
                                vo.setO3(df.format(Double.valueOf(vo.getO3()) + Double.valueOf(s.getO3())*f));
                                vo.setAqi(df.format(Double.valueOf(vo.getAqi()) + Double.valueOf(s.getAqi())*f));
                                if(disTime < 24){
                                    vo.setPm25r(df.format(Double.valueOf(vo.getPm25r()) + Double.valueOf(s.getPm25r())*f));
                                    vo.setPm10r(df.format(Double.valueOf(vo.getPm10r()) + Double.valueOf(s.getPm10r())*f));
                                }else {
                                    vo.setPm10r("—");
                                    vo.setPm25r("—");
                                }
                            }
                        });

                    }else {
                        BeanUtils.copyProperties(v.get(0),vo);
                        vo.setSiteName(k);
                    }
                }else {
                    BeanUtils.copyProperties(v.get(0),vo);
                    vo.setSiteName(k);
                }
                v.add(vo);
            });
//        Map<String,List<CheckDataVo>> res = new HashMap<>();
//        Map<String,List<CheckDataVo>> maps = checkDataVos.stream().collect(Collectors.groupingBy(CheckDataVo::getSiteName));
//        countyMap.forEach((k,v)->{
//            List<CheckDataVo> ls = new ArrayList<>();
//            if (v.size() == 2){
//                v.forEach(s->{
//                    CheckDataVo vo = maps.get(s).get(0);
//                    if (vo!=null){
//
//                    }
//                });
//            }else {
//                v.forEach(s->{
//
//                });
//            }
//
//        });
            return ResultGenerator.genSuccessResult(res);
        }catch (Exception e){
            return ResultGenerator.genFailResult("数据异常，请检查上传数据！");
        }
    }
//    @ApiImplicitParam(name = "hourTime", value = "时间", required = false)
//    @ApiOperation("查")
//    @GetMapping("/query")
//    public Result query(String hourTime) {
//        LocalDateTime time = LocalDateTime.parse(hourTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//        System.out.println(time.toLocalDate());
//        List<CheckData> list = checkDataService.list(new LambdaQueryWrapper<CheckData>()
//            .ge(CheckData::getCollectTime,time.toLocalDate())
//            .le(CheckData::getCollectTime,hourTime)
//            .orderByAsc(CheckData::getCollectTime)
//        );
//        Map<String,List<CheckData>> map = list.stream().collect(Collectors.groupingBy(CheckData::getSiteName));
//        // 当前时刻
//        Map<String,List<CheckData>> mapc = list.stream().filter(s->s.getCollectTime().equals(hourTime))
//                .collect(Collectors.groupingBy(CheckData::getSiteName));
//        List<CheckDataVo> res = new ArrayList<>();
//        DecimalFormat df = new DecimalFormat("#.###");
//        map.forEach((k,v)->{
//            CheckDataVo checkDataVo = new CheckDataVo();
//            checkDataVo.setSiteName(k);
//            checkDataVo.setPm25(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getPm25())))));
//            checkDataVo.setPm10(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getPm10())))));
//            checkDataVo.setNo2(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getNo2())))));
//            checkDataVo.setCo(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getCo())))));
//            checkDataVo.setAqi(df.format(v.stream().collect(Collectors.averagingDouble(s->Double.valueOf(s.getAqi())))));
//            if (mapc.get(k)!=null){
//                checkDataVo.setPpc(mapc.get(k).get(0).getPp());
//                checkDataVo.setAqic(mapc.get(k).get(0).getAqi());
//            }
//            checkDataVo.setCountyName(siteMap.get(k));
//            res.add(checkDataVo);
//        });
//
//        return ResultGenerator.genSuccessResult(res.stream().collect(Collectors.groupingBy(CheckDataVo::getCountyName)));
//    }
}
